home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Graphics Plus
/
Graphics Plus.iso
/
general
/
viewers
/
polyview
/
polyvw31.lha
/
Polyview3.1
/
new
/
pvray.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-06-23
|
23KB
|
788 lines
/*****************************************************************************
* NCSA Polyview 3.0 *
* *
* Version 3 changes and additions by Marc Andreessen. *
* Version 2 by Brian Calvert. *
* *
* Software Development Group *
* National Center for Supercomputing Applications *
* University of Illinois at Urbana-Champaign *
* *
* This is BETA release software. As such it may contain software bugs and *
* exhibit inconsistencies. *
* *
* Please send bug reports to polyview@ncsa.uiuc.edu. *
* *
* Copyright (c) 1992 The Board of Trustees of the University of Illinois. *
* *
* Permission to use, copy, and modify this software and its *
* documentation for educational, research, and non-profit purposes is *
* hereby granted, provided that the above copyright notice, the original *
* authors names, and this permission notice appear in all such copies. *
* Any distribution of this software requires the explicit and written *
* authorization of the authors. *
* *
* The University of Illinois makes no representations about the *
* suitability of this software for any purpose. It is provided "as is" *
* without warranty of any kind. *
*****************************************************************************/
/* $Header: /usr3/people/gbourhis/pv3/new/RCS/pvray.c,v 1.1 92/09/18 10:55:26 marca Exp $ */
#ifdef RCSLOG
$Log: pvray.c,v $
* Revision 1.1 92/09/18 10:55:26 marca
* Initial revision
*
#endif
#include "pv.h"
/* ------------------------------------------------------------------------ */
/* ----------------------- RAYSHADE OUTPUT ROUTINES ----------------------- */
/* ------------------------------------------------------------------------ */
static FILE *rayfp = NULL;
static void ray_bgnpolygon (void)
{
fprintf (rayfp, " poly \n");
return;
}
static void ray_v3f (float *vv)
{
fprintf (rayfp, " %f %f %f\n", vv[0], vv[1], vv[2]);
return;
}
static void ray_endpolygon (void)
{
return;
}
static void ray_palettecpack (int c)
{
fprintf (rayfp, " pal%1d\n", c);
return;
}
/* Keep a static array of vertices and a count of the number
of vertices in the array. */
static float line_vv[20][3];
static int line_vv_count = 0;
static int line_cc[20];
static int line_cc_used = 0;
/* Static width of lines drawn as cylinders. */
static float line_width = 0.1;
/* This should be a window-local variable or something. */
static int cap_cylinders = 0;
static void ray_linepalettecpack (int c)
{
/* Save this color index with the current vertex. */
line_cc[line_vv_count] = c;
/* Note that we are using colors for this line. */
line_cc_used = 1;
}
static void ray_bgnclosedline (void)
{
/* Starting a new line. */
line_vv_count = 0;
/* Haven't used any colors yet. */
line_cc_used = 0;
}
static void ray_endclosedline (void)
{
int i;
/* If we have one or fewer vertices, punt. */
if (line_vv_count < 2)
goto done;
/* For each vertex up to the second-to-last, make
a cylinder with the vertex and its successor. */
for (i = 0; i < line_vv_count - 1; i++)
{
fprintf (rayfp, " cylinder\n");
if (line_cc_used)
{
/* We've used colors, so set a color. */
fprintf (rayfp, " pal%1d\n", line_cc[i]);
}
fprintf (rayfp, " %s\n %f %f %f\n %f %f %f\n",
/* radius */ "CYL_RAD",
/* end 1 */ line_vv[i][0], line_vv[i][1], line_vv[i][2],
/* end 2 */ line_vv[i+1][0], line_vv[i+1][1], line_vv[i+1][2]);
if (cap_cylinders)
{
fprintf (rayfp, " disc\n");
if (line_cc_used)
fprintf (rayfp, " pal%1d\n", line_cc[i]);
fprintf (rayfp, " %s\n %f %f %f\n %f %f %f\n",
"CYL_RAD",
line_vv[i][0], line_vv[i][1], line_vv[i][2],
line_vv[i][0] - line_vv[i+1][0],
line_vv[i][1] - line_vv[i+1][1],
line_vv[i][2] - line_vv[i+1][2]);
fprintf (rayfp, " disc\n");
if (line_cc_used)
fprintf (rayfp, " pal%1d\n", line_cc[i]);
fprintf (rayfp, " %s\n %f %f %f\n %f %f %f\n",
"CYL_RAD",
line_vv[i+1][0], line_vv[i+1][1], line_vv[i+1][2],
line_vv[i+1][0] - line_vv[i][0],
line_vv[i+1][1] - line_vv[i][1],
line_vv[i+1][2] - line_vv[i][2]);
}
}
/* If there's more than 2 vertices, close the line. */
if (line_vv_count > 2)
{
i = line_vv_count - 1;
fprintf (rayfp, " cylinder\n");
if (line_cc_used)
{
fprintf (rayfp, " pal%1d\n", line_cc[i]);
}
fprintf (rayfp, " %s\n %f %f %f\n %f %f %f\n",
/* radius */ "CYL_RAD",
/* end 1 */ line_vv[i][0], line_vv[i][1], line_vv[i][2],
/* end 2 */ line_vv[0][0], line_vv[0][1], line_vv[0][2]);
if (cap_cylinders)
{
fprintf (rayfp, " disc\n");
if (line_cc_used)
fprintf (rayfp, " pal%1d\n", line_cc[i]);
fprintf (rayfp, " %s\n %f %f %f\n %f %f %f\n",
"CYL_RAD",
line_vv[i][0], line_vv[i][1], line_vv[i][2],
line_vv[i][0] - line_vv[0][0],
line_vv[i][1] - line_vv[0][1],
line_vv[i][2] - line_vv[0][2]);
fprintf (rayfp, " disc\n");
if (line_cc_used)
fprintf (rayfp, " pal%1d\n", line_cc[i]);
fprintf (rayfp, " %s\n %f %f %f\n %f %f %f\n",
"CYL_RAD",
line_vv[0][0], line_vv[0][1], line_vv[0][2],
line_vv[0][0] - line_vv[i][0],
line_vv[0][1] - line_vv[i][1],
line_vv[0][2] - line_vv[i][2]);
}
}
done:
line_vv_count = 0;
return;
}
static void ray_linev3f (float *vv)
{
/* Store this vertex. */
line_vv[line_vv_count][0] = vv[0];
line_vv[line_vv_count][1] = vv[1];
line_vv[line_vv_count][2] = vv[2];
/* Increment the count. */
line_vv_count++;
return;
}
/* ------------------------------------------------------------------------ */
/* ------------------------ SPHERE RAY/GL ROUTINES ------------------------ */
/* ------------------------------------------------------------------------ */
static float sphere_size;
/* 1 if vertices should be drawn as cubes. */
static int sphere_cubes;
static int sphere_col_set = 0;
static int sphere_col;
static void ray_sphpalettecpack (int c)
{
sphere_col_set = 1;
sphere_col = c;
return;
}
static void ray_sphdraw (float *vv)
{
if (sphere_cubes)
{
fprintf (rayfp, " box\n");
if (sphere_col_set)
fprintf (rayfp, " pal%1d\n", sphere_col);
fprintf (rayfp, " (%f-SPH_RAD) (%f-SPH_RAD) (%f-SPH_RAD)\n",
vv[0],
vv[1],
vv[2]);
fprintf (rayfp, " (%f+SPH_RAD) (%f+SPH_RAD) (%f+SPH_RAD)\n",
vv[0],
vv[1],
vv[2]);
}
else
{
fprintf (rayfp, " sphere\n");
if (sphere_col_set)
fprintf (rayfp, " pal%1d\n", sphere_col);
fprintf (rayfp, " %s\n", "SPH_RAD");
fprintf (rayfp, " %f %f %f\n", vv[0], vv[1], vv[2]);
}
/* Make sure we don't repeat a color. */
sphere_col_set = 0;
return;
}
static int ray_draw_vertices (state_t *state, window_t *win, object_t *obj,
objinfo_t *info)
{
long count;
Vdata_t **vdata;
Vdata_t *vcolor_v;
Vdata_t *pcoord_v;
float (*pcoord)[DIMS];
int *vcolor;
char *picked;
int single_color;
/* Get pointers to the pertinent data sets */
vdata = obj->u.obj.vdata;
vcolor_v = get_vdata(state, vdata[VCOLOR]);
if ((pcoord_v = get_vdata(state, vdata[PCOORD])) == NULL)
return ST_OKAY;
/* Set up the consolidated coordinate array pointer. */
pcoord = (float (*)[DIMS]) pcoord_v->data;
count = pcoord_v->stats[0].rec_count;
assert (pcoord_v->stats[0].type == PVFLOAT);
if (FEQ(win->sphere_size, 0.0))
sphere_size = win->max_width * 0.01;
else
sphere_size = win->sphere_size;
fprintf (rayfp, "#define SPH_RAD %f\n", sphere_size);
sphere_cubes = (win->sphere_depth == 1);
if (vcolor_v == NULL || vcolor_v->data == NULL)
{
/* No color information. Use foreground and draw the */
/* appropriate shapes. */
while (count > 0)
{
{ /* not selected */
float params[4];
params[0] = (*pcoord)[0];
params[1] = (*pcoord)[1];
params[2] = (*pcoord)[2];
params[3] = win->sphere_size;
ray_sphdraw (params);
}
/* Move to the next x, y, z set and decrement the */
/* count. */
pcoord++;
count--;
}
}
else
{
/* Set pointers to the actual data and the size of the data */
/* sets. */
assert (vcolor_v->stats[0].type == PVINTEGER);
/* There is color information. Get it and use it to draw the */
/* appropriate shapes. */
vcolor = (int *) vcolor_v->data;
while (count > 0)
{
{ /* not selected */
float params[4];
ray_sphpalettecpack(*vcolor);
params[0] = (*pcoord)[0];
params[1] = (*pcoord)[1];
params[2] = (*pcoord)[2];
params[3] = win->sphere_size;
ray_sphdraw (params);
}
/* Move to the next x, y, z set, color entry, and */
/* decrement the count. */
pcoord++;
vcolor++;
count--;
}
}
return ST_OKAY;
}
static int ray_draw_edges (state_t *state, window_t *win, object_t *obj,
objinfo_t *info)
{
long count;
Vdata_t **vdata, *vcolor_v, *pcoord_v, *connect_v;
float (*pcoord)[DIMS];
int *vcolor, *connect;
char *picked;
int i, nvert, vertex;
/* Set the width of the cylinders. */
line_width = WIN_MAXWIDTH(win) * 0.0005 * (float)(win->line_width);
fprintf (rayfp, "#define CYL_RAD %f\n", line_width);
/* Get pointers to the pertinent data sets. */
vdata = obj->u.obj.vdata;
vcolor_v = get_vdata(state, vdata[VCOLOR]);
if ((connect_v = get_vdata(state, vdata[CONNECT])) == NULL)
if ((connect_v = get_vdata(state, vdata[MCONNECT])) == NULL)
{
ray_draw_vertices(state, win, obj, info);
return ST_OKAY;
}
if ((pcoord_v = get_vdata(state, vdata[PCOORD])) == NULL)
return ST_OKAY;
/* Collect connectivity information for drawing. */
connect = (int *) connect_v->data;
count = connect_v->stats[0].rec_count;
nvert = connect_v->stats[0].rec_size;
/* Set up the consolidated coordinate array pointer. */
pcoord = (float (*)[DIMS]) pcoord_v->data;
assert (pcoord_v->stats[0].type == PVFLOAT);
/* If there is no vertex color information, draw without it */
/* (use the FOREGROUND color). Otherwise, grab the color array. */
if (vcolor_v == NULL || vcolor_v->data == NULL)
{
/* No color information. Use foreground and draw the */
/* appropriate shapes. */
while (count > 0)
{
ray_bgnclosedline();
for (i = nvert; i > 0; i--)
{
if ( (vertex = *(connect++)-1) == -1)
{
connect += i-1;
break;
}
ray_linev3f(pcoord[vertex]);
}
ray_endclosedline();
count--;
}
}
else
{
/* Set pointers to the actual data and the size of the data */
/* sets. */
assert (vcolor_v->stats[0].type == PVINTEGER);
/* There is color information. Get it and use it to draw the */
/* appropriate shapes. */
vcolor = (int *) vcolor_v->data;
while (count > 0)
{
ray_bgnclosedline();
for (i = nvert; i > 0; i--)
{
if ( (vertex = *(connect++)-1) == -1)
{
connect += i-1;
break;
}
ray_linepalettecpack(vcolor[vertex]);
ray_linev3f(pcoord[vertex]);
}
ray_endclosedline();
count--;
}
}
return ST_OKAY;
}
static int ray_draw_faces (state_t *state, window_t *win, object_t *obj,
objinfo_t *info)
{
long count;
Vdata_t **vdata, *vcolor_v, *pcoord_v, *connect_v;
float (*pcoord)[DIMS];
int *vcolor, *connect;
char *picked;
int i, nvert, vertex, single_color;
/* Get pointers to the pertinent data sets */
vdata = obj->u.obj.vdata;
vcolor_v = get_vdata(state, vdata[VCOLOR]);
if ( (connect_v = get_vdata(state, vdata[CONNECT])) == NULL)
if ( (connect_v = get_vdata(state, vdata[MCONNECT])) == NULL)
return ray_draw_vertices(state, win, obj, info);
/* If the plist does not describe polygons, draw edges. */
if (connect_v->stats[0].rec_size < 3)
return ray_draw_edges(state, win, obj, info);
if ( (pcoord_v = get_vdata(state, vdata[PCOORD])) == NULL)
return ST_OKAY;
/* Collect connectivity information for drawing. */
connect = (int *) connect_v->data;
count = connect_v->stats[0].rec_count;
nvert = connect_v->stats[0].rec_size;
/* Set up the consolidated coordinate array pointer. */
pcoord = (float (*)[DIMS]) pcoord_v->data;
assert (pcoord_v->stats[0].type == PVFLOAT);
/* If there is no vertex color information, draw without it */
/* (use the FOREGROUND color). Otherwise, grab the color array. */
if (vcolor_v == NULL || vcolor_v->data == NULL)
{
while (count > 0)
{
ray_bgnpolygon();
for (i = nvert; i > 0; i--)
{
if ( (vertex = *(connect++)-1) == -1)
{
connect += i-1;
break;
}
ray_v3f(pcoord[vertex]);
}
ray_endpolygon();
count--;
}
}
else
{
/* Set pointers to the actual data and the size of the data */
/* sets. */
assert (vcolor_v->stats[0].type == PVINTEGER);
/* There is color information. Get it and use it to draw the */
/* appropriate shapes. */
vcolor = (int *) vcolor_v->data;
while (count > 0)
{
ray_bgnpolygon();
for (i = nvert; i > 0; i--)
{
if ((vertex = *(connect++)-1) == -1)
{
connect += i-1;
break;
}
if (i == nvert)
ray_palettecpack (vcolor[vertex]);
ray_v3f(pcoord[vertex]);
}
ray_endpolygon();
count--;
}
}
return ST_OKAY;
}
static int ray_draw_outlined_faces(state_t *state, window_t *win,
object_t *obj,
objinfo_t *info)
{
long count;
Vdata_t **vdata, *vcolor_v, *pcoord_v, *connect_v;
float (*pcoord)[DIMS];
float pcoord_outline[DIMS];
int *vcolor, *connect, *oconnect;
char *picked;
int i, j, nvert, vertex, single_color;
/* Set the width of the cylinders. */
line_width = WIN_MAXWIDTH(win) * 0.0005 * (float)(win->line_width);
fprintf (rayfp, "#define CYL_RAD %f\n", line_width);
/* Get pointers to the pertinent data sets */
vdata = obj->u.obj.vdata;
vcolor_v = get_vdata(state, vdata[VCOLOR]);
if ( (connect_v = get_vdata(state, vdata[CONNECT])) == NULL)
if ( (connect_v = get_vdata(state, vdata[MCONNECT])) == NULL)
return ray_draw_vertices(state, win, obj, info);
/* If the plist does not describe polygons, draw edges. */
if (connect_v->stats[0].rec_size < 3)
return ray_draw_edges(state, win, obj, info);
if ( (pcoord_v = get_vdata(state, vdata[PCOORD])) == NULL)
return ST_OKAY;
/* Collect connectivity information for drawing. */
oconnect = connect = (int *) connect_v->data;
count = connect_v->stats[0].rec_count;
nvert = connect_v->stats[0].rec_size;
/* Set up the consolidated coordinate array pointer. */
pcoord = (float (*)[DIMS]) pcoord_v->data;
assert (pcoord_v->stats[0].type == PVFLOAT);
/* If there is no vertex color information, draw without it. */
/* Otherwise, grab the color array. */
if (vcolor_v == NULL || vcolor_v->data == NULL)
{
while (count > 0)
{
/* Save connectivity pointer. */
oconnect = connect;
/* Draw the polygon. */
ray_bgnpolygon();
for (i = nvert; i > 0; i--)
{
if ( (vertex = *(connect++)-1) == -1)
{
connect += i-1;
break;
}
ray_v3f(pcoord[vertex]);
}
ray_endpolygon();
/* Start connectivity anew. */
connect = oconnect;
/* Draw the outline of the polygon, with Z values */
ray_bgnclosedline();
for (i = nvert; i > 0; i--)
{
if ( (vertex = *(connect++)-1) == -1)
{
connect += i-1;
break;
}
ray_linev3f(pcoord[vertex]);
}
ray_endclosedline();
count--;
}
}
else
{
/* Set pointers to the actual data and the size of the data */
/* sets. */
assert (vcolor_v->stats[0].type == PVINTEGER);
/* There is color information. Get it and use it to draw the */
/* appropriate shapes. */
vcolor = (int *) vcolor_v->data;
while (count > 0)
{
/* Save connectivity pointer. */
oconnect = connect;
/* Draw the polygon. */
ray_bgnpolygon();
for (i = nvert; i > 0; i--)
{
if ( (vertex = *(connect++)-1) == -1)
{
connect += i-1;
break;
}
if (i == nvert)
ray_palettecpack(vcolor[vertex]);
ray_v3f(pcoord[vertex]);
}
ray_endpolygon();
/* Start connectivity anew. */
connect = oconnect;
/* Draw the outline of the polygon, with Z values */
ray_bgnclosedline();
for (i = nvert; i > 0; i--)
{
if ( (vertex = *(connect++)-1) == -1)
{
connect += i-1;
break;
}
ray_linev3f(pcoord[vertex]);
}
ray_endclosedline();
count--;
}
}
return ST_OKAY;
}
void dump_ray (state_t *state, window_t *win, char *fname)
{
polyview_t *pv;
object_t *obj;
int i;
assert (win->type == POLYVIEW);
pv = (polyview_t *)WIN_IMAGE(win);
rayfp = fopen (fname, "w");
if (rayfp == NULL)
{
stprintf (state, "Could not open output file.");
return;
}
fprintf (rayfp, "/* NCSA Polyview 3.0 rayshade output file. */\n\n");
fprintf (rayfp, "/* National Center for Supercomputing Applications */\n");
fprintf (rayfp, "/* University of Illinois at Urbana-Champaign */\n");
fprintf (rayfp, "/* polyview@ncsa.uiuc.edu */\n\n");
fprintf (rayfp, "eyep %f %f %f\n", win->cfrom[X], win->cfrom[Y],
win->cfrom[Z]);
fprintf (rayfp, "lookp %f %f %f\n", win->at[X], win->at[Y], win->at[Z]);
fprintf (rayfp, "up 0 -1 0\n\n");
fprintf (rayfp, "background 0 0 0\n\n");
fprintf (rayfp, "screen %d %d\n\n", pv->dv_width, pv->dv_height);
/* default light is directional, intensity 1.0, (1 -1 1). */
fprintf (rayfp, "light 1.0 point %f %f %f\n\n",
win->cfrom[X] * 1.5, win->cfrom[Y] * 1.5, win->cfrom[Z] * 1.5);
if (WIN_DRAW(win) == DrawTrans)
fprintf (rayfp, "#define TRANSP_COEF 0.4\n");
if (WIN_DRAW(win) == draw_vertices)
fprintf (rayfp, "#define REFL_COEF 0.5\n");
for (i = 0; i < 256; i++)
{
fprintf (rayfp,
"surface pal%1d\n ambient %f %f %f\n diffuse %f %f %f\n",
i,
(float)state->pal[i][0]/760.0,
(float)state->pal[i][1]/760.0,
(float)state->pal[i][2]/760.0,
(float)state->pal[i][0]/255.0,
(float)state->pal[i][1]/255.0,
(float)state->pal[i][2]/255.0);
if (WIN_DRAW(win) == DrawTrans)
fprintf (rayfp, " transp TRANSP_COEF\n");
if (WIN_DRAW(win) == draw_vertices)
fprintf (rayfp, " reflect REFL_COEF\n");
}
fprintf (rayfp, "\n");
if (WIN_FRAME(win) == NULL)
{
assert (WIN_FRAMELIST(win) == NULL);
return;
}
obj = FRA_ROOTOBJ (WIN_FRAME(win));
/* Make sure that the object exists, has information associated */
/* with it, and has a drawing function. */
assert (obj != NULL);
assert (obj->info != NULL);
assert (obj->info->draw_fn != NULL);
fprintf (rayfp, "grid 8 8 8\n");
if (WIN_DRAW(win) == draw_faces)
ray_draw_faces (state, win, obj, obj->info);
if (WIN_DRAW(win) == draw_edges)
ray_draw_edges (state, win, obj, obj->info);
if (WIN_DRAW(win) == draw_outlined_faces || WIN_DRAW(win) == DrawTrans ||
WIN_DRAW(win) == draw_hidden_edges)
ray_draw_outlined_faces (state, win, obj, obj->info);
if (WIN_DRAW(win) == draw_vertices)
ray_draw_vertices (state, win, obj, obj->info);
fprintf (rayfp, "end /* grid */\n");
fclose (rayfp);
rayfp = NULL;
return;
}